package Util

import (
	"errors"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"

	"github.com/dgrijalva/jwt-go"
)

// JwtClaims 创建自己的Claims
type JwtClaims struct {
	*jwt.StandardClaims
	//用户编号
	UID      int
	Username string
}

// 登录的参数
type UserLogin struct {
	UserName string `json:"user_name"` //用户名
	Password string `json:"password"`  //密码，对明文密码进行sha256
}

var (
	//盐
	secret                 = []byte("wondersafebox")                   // 后续加密增加盐增加复杂度
	TokenExpired     error = errors.New("Token is expired")            // token错误类型提炼
	TokenNotValidYet error = errors.New("Token not active yet")        // token错误类型提炼
	TokenMalformed   error = errors.New("That's not even a token")     // token错误类型提炼
	TokenInvalid     error = errors.New("Couldn't handle this token:") // token错误类型提炼
)

// CreateJwtToken 生成一个jwttoken
func CreateJwtToken(id int, username string) (string, error) {

	// 定义过期时间,7天后过期
	expireToken := time.Now().Add(time.Hour * 24 * 1000).Unix()

	claims := JwtClaims{
		&jwt.StandardClaims{
			NotBefore: int64(time.Now().Unix() - 1000), // token信息生效时间
			ExpiresAt: int64(expireToken),              // 过期时间
			Issuer:    "wonders",                       // 发布者
		},
		id,
		username,
	}
	// 对自定义claims加密,jwt.SigningMethodHS256是加密算法得到第二部分
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	// 给这个token盐加密 第三部分,得到一个完整的三段的加密
	signedToken, err := token.SignedString(secret)
	if err != nil {
		return "", err
	}
	return signedToken, nil
}

// ParseJwtToken 解析token得到是自己创建的Claims
func ParseJwtToken(jwtToken string) (*JwtClaims, error) {
	var jwtclaim = &JwtClaims{}
	_, err := jwt.ParseWithClaims(jwtToken, jwtclaim, func(*jwt.Token) (interface{}, error) {
		//得到盐
		return secret, nil
	})
	if err != nil {
		if ve, ok := err.(*jwt.ValidationError); ok {
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, TokenMalformed
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				// Token is expired
				return nil, TokenExpired
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, TokenNotValidYet
			} else {
				return nil, TokenInvalid
			}
		}
	}
	return jwtclaim, nil
}

// 校验token中间件
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从请求头中获取token
		tokeString := c.GetHeader("token")
		if tokeString == "" {
			c.JSON(http.StatusOK, gin.H{
				"code": 0,
				"data": "",
				"msg":  "必须传递token",
			})
			c.Abort()
			return
		}
		claims, err := ParseJwtToken(tokeString)
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 0,
				"data": "",
				"msg":  "token解析错误",
			})
			c.Abort()
			return
		}
		// 从token中解析出来的数据挂载到上下文上,方便后面的控制器使用
		c.Set("userId", claims.UID)
		c.Set("userName", claims.Username)
		c.Next()
	}
}
